'''
Created on 17/02/2010

@author: eh01
'''
from myschema import Import, Schema, Type
import myschema
import myxml

class WSDL(object):
    
    def __init__(self):
        self.wsdl_type = None
        self.service = None
        self.target_namespace = None
        self.imported_namespaces = None
        
class WSDLType(object):

    def __init__(self):
        self.schema = None

class Service(object):
    
    def __init__(self):
        self.name = None
        self.port = None

class Port(object):
    
    def __init__(self):
        self.name = None
        self.address = None
        self.port_type = None
        self.binding = None

class PortType(object):
    
    def __init__(self):
        self.operations = {}

class Operation(object):
    
    def __init__(self):
        self.name = None        
        self.input = None
        self.output = None
        self.fault = None
        self.soap_action = None

class Input(object):
    
    def __init__(self):
        self.name = None        
        self.message = None
        self.action = None

class Output(object):
    
    def __init__(self):
        self.name = None        
        self.message = None
        self.action = None

class Fault(object):
    
    def __init__(self):
        self.name = None        
        self.message = None
        self.action = None
    
class Message(object):
    
    def __init__(self):
        self.name = None
        self.part =  None

class Part(object):
    
    def __init__(self):
        self.name = None
        self.element = None

class Binding(object):
    
    def __init__(self):
        self.operations = {}
        
def parse(wsdl_file_path):
    wsdl_file_fp = get_raw_wsdl_file(wsdl_file_path)   
    root_element_tree = myxml.pre_parse_xml_to_add_namespace_data_to_elements(wsdl_file_fp)
    wsdl_element = root_element_tree
    wsdl = WSDL()
    wsdl.target_namespace = wsdl_element.attrib['targetNamespace']
    wsdl.imported_namespaces = wsdl_element.ns_map    
    
    # get types
    type_element = wsdl_element.find('./{http://schemas.xmlsoap.org/wsdl/}types')
    wsdl_type = WSDLType()
    wsdl.wsdl_type = wsdl_type
    
    # get schema    
    schema_element = type_element.find('./{http://www.w3.org/2001/XMLSchema}schema')
    schema = Schema()
    wsdl_type.schema = schema
    
    # get imports
    for import_element in schema_element.findall('./{http://www.w3.org/2001/XMLSchema}import'):
        imp = Import()
        imp.namespace = import_element.attrib['namespace']
        imp.schema_location = import_element.attrib['schemaLocation']    
        schema.imports.append(imp)  
    
    # get service
    # assume one service per wsdl
    service_element = wsdl_element.find('./{http://schemas.xmlsoap.org/wsdl/}service')
    service = Service()
    wsdl.service = service
    service.name = service_element.attrib['name']
    
    wsdl.service = service
    service.name = service_element.attrib['name']
    
    # get port
    # assume one port per service
    port_element = service_element.find('./{http://schemas.xmlsoap.org/wsdl/}port')
    port = Port()
    service.port = port
    port.name = port_element.attrib['name']
    address_element = port_element.find('./{http://schemas.xmlsoap.org/wsdl/soap/}address')
    port.address = address_element.attrib['location']

    # get binding
    # assume one binding in the same wsdl and assume http binding
    binding = Binding()
    port.binding = binding
    binding_element = wsdl_element.find('./{http://schemas.xmlsoap.org/wsdl/}binding')
    for operation_element in binding_element.findall('./{http://schemas.xmlsoap.org/wsdl/}operation'):
        operation = Operation()
        operation.name = operation_element.attrib['name']        
        operation.soap_action = operation_element.find('./{http://schemas.xmlsoap.org/wsdl/soap/}operation').attrib['soapAction'] 
        binding.operations[operation.name] = operation
    
    # get port type
    port_type_element = wsdl_element.find('./{http://schemas.xmlsoap.org/wsdl/}portType')
    port_type = PortType()
    port.port_type = port_type
    port_type.name = port_type_element.attrib['name']
    
    # get operation
    for operation_element in port_type_element.findall('./{http://schemas.xmlsoap.org/wsdl/}operation'):
        operation = Operation()
        operation.name = operation_element.attrib['name']
        input_element = operation_element.find('./{http://schemas.xmlsoap.org/wsdl/}input')
        input_message_element = find_message_element_by_name(input_element.attrib['message'], wsdl_element)
        input_message = parse_message(input_message_element)
        input = Input()
        input.message = input_message
        output_element = operation_element.find('./{http://schemas.xmlsoap.org/wsdl/}output')
        output_message_element = find_message_element_by_name(output_element.attrib['message'], wsdl_element)
        output_message = parse_message(output_message_element)
        output = Output()
        output.message = output_message                
        fault_element = operation_element.find('./{http://schemas.xmlsoap.org/wsdl/}fault')
        fault_message_element = find_message_element_by_name(fault_element.attrib['message'], wsdl_element)
        fault_message = parse_message(fault_message_element)
        fault = Fault()
        fault.message = fault_message
        operation.input = input
        operation.output = output
        operation.fault = fault
        port_type.operations[operation.name] = operation
        
    return wsdl

def parse_input_output_fault_element(input_output_fault_element, input_output_fault, wsdl_element):
    message_element = find_message_element_by_name(input_output_fault_element.attrib['message'], wsdl_element)
    input_message = parse_message(message_element)
    input_output_fault.message = input_message
    if 'name' in input_output_fault_element.attrib.keys():
        input_output_fault.name = input_output_fault_element.attrib['name']
    if '{http://www.w3.org/2006/05/addressing/wsdl}/Action' in input_output_fault_element.attrib.keys():
        input_output_fault.action = input_output_fault_element.attrib['{http://www.w3.org/2006/05/addressing/wsdl}/Action']

def find_message_element_by_name(message_element_name, wsdl_element):
    # remove the namespace prefix
    message_element_name = message_element_name.partition(':')[2]
    for message_element in wsdl_element.findall('./{http://schemas.xmlsoap.org/wsdl/}message'):
        if message_element_name == message_element.attrib['name']:
            return message_element
    return None
    
def parse_message(message_element):
    message = Message()
    message.name = message_element.attrib['name']
    # assume one part per message
    part_element = message_element.find('./{http://schemas.xmlsoap.org/wsdl/}part')
    part = Part()
    message.part = part    
    part.name = part_element.attrib['name']
    type = myschema.create_type(part_element.attrib['element'], part_element)
    part.element = type
    return message

def get_raw_wsdl_file(wsdl_file_path): 
    wsdl_file_fp = open(wsdl_file_path, 'rb')
    return wsdl_file_fp 